#include "../header/reactor.h"

void Reactor::Reactor_init(){
    _epfd = epoll_create(1);
    _fd = socket(AF_INET, SOCK_STREAM, 0);

	struct sockaddr_in servaddr;
	servaddr.sin_family = AF_INET;
	// servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0
	servaddr.sin_port = htons(_port); // 0-1023, 
    if(inet_pton(AF_INET, _ip.c_str(), &servaddr.sin_addr) <= 0)
        cout<<"ip error"<<endl;

	if (bind(_fd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr)) == -1) {
		cout << "bind failed: " << strerror(errno) << endl;
	}

	listen(_fd, 10);

    conn_list[_fd].fd = _fd;
    set_event(_fd, EPOLLIN, 1);
	gettimeofday(&begin, NULL);
}

int Reactor::accept_cb(){
    struct sockaddr_in  clientaddr;
	socklen_t len = sizeof(clientaddr);

	int clientfd = accept(_fd, (struct sockaddr*)&clientaddr, &len);
	//printf("accept finshed: %d\n", clientfd);
	if (clientfd < 0) {
		printf("accept errno: %d --> %s\n", errno, strerror(errno));
		return -1;
	}
	conn_list[clientfd].fd = clientfd;

	// memset(conn_list[clientfd].rbuffer, 0, BUFFER_LENGTH);
	// conn_list[clientfd].rlength = 0;

	// memset(conn_list[clientfd].wbuffer, 0, BUFFER_LENGTH);
	// conn_list[clientfd].wlength = 0;

	set_event(clientfd, EPOLLIN, 1);  // | EPOLLET

	if ((clientfd % 1000) == 0) {

		struct timeval current;
		gettimeofday(&current, NULL);

		int time_used = TIME_SUB_MS(current, begin);
		memcpy(&begin, &current, sizeof(struct timeval));
		

		printf("accept finshed: %d, time_used: %d\n", clientfd, time_used);

	}

	return 0;
}

void Reactor::set_event(int fd, int event, int flag){
	if (flag) {  // non-zero add

		struct epoll_event ev;
		ev.events = event;
		ev.data.fd = fd;
		epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &ev);

	} else {  // zero mod

		struct epoll_event ev;
		ev.events = event;
		ev.data.fd = fd;
		epoll_ctl(_epfd, EPOLL_CTL_MOD, fd, &ev);
		
	}
	    
}

int Reactor::recv_cb(int fd){
    memset(conn_list[fd].rbuffer, 0, BUFFER_LENGTH );
    int count = recv(fd, conn_list[fd].rbuffer, BUFFER_LENGTH, 0);
	if (count == 0) { // disconnect
		printf("client disconnect: %d\n", fd);
		close(fd);

		epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, NULL); // unfinished

		return 0;
	} else if (count < 0) { // 

		printf("count: %d, errno: %d, %s\n", count, errno, strerror(errno));
		close(fd);
		epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, NULL);

		return -1;
	}
    conn_list[fd].rlength = count;
#if 0
    // 环回
    conn_list[fd].wlength = conn_list[fd].rlength;
	memcpy(conn_list[fd].wbuffer, conn_list[fd].rbuffer, conn_list[fd].wlength);
    // 打印
	printf("[%d]RECV: %s\n", conn_list[fd].rlength, conn_list[fd].rbuffer);
#else

#endif

	_work.recv_done(conn_list[fd].rbuffer);

    set_event(fd, EPOLLOUT, 0);
    return count;
}

int Reactor::send_cb(int fd){
    int count = 0;
	_work.send_done(conn_list[fd].wbuffer, conn_list[fd].wlength);

	if (conn_list[fd].wlength != 0) {
		count = send(fd, conn_list[fd].wbuffer, conn_list[fd].wlength, 0);
		if(count < 0){
			count<< "send error "<<endl;
		}
	}
	set_event(fd, EPOLLIN, 0);  
    return count;  
}

void Reactor::Run(){

    while(1){
        struct epoll_event events[1024] = {0};
        int nready = epoll_wait(_epfd, events, 1024, -1);

        int i = 0;
        for(i = 0; i < nready; i++){
            int connfd = events[i].data.fd;

            if(events[i].events & EPOLLIN){
                if(events[i].data.fd == _fd)
                    accept_cb();
                else
                    recv_cb(connfd);
            }
            if(events[i].events & EPOLLOUT){
                send_cb(connfd);
            }

        }
    }
}